import json
import random
import re
from io import BytesIO
from django.contrib.auth import authenticate
import redis
from django.utils.decorators import method_decorator
from qrcode import QRCode, constants
import pyotp
from django.views.decorators.csrf import csrf_exempt
from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
from django.http import JsonResponse, HttpResponse
from django.views import View
import requests
from myapp.models import UserInfo
# from ldap3 import Server, Connection, SUBTREE

from myapp.roles import rolesoperate


class SendVerificationCodeView_AddAndBindGoogleAuthView(View):

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        action = kwargs.pop('action', None)
        if action == 'AddAndBindGoogleAuthView':
            return self.get(request, *args, **kwargs)
        elif action == 'SendVerificationCodeView':
            return self.post(request, *args, **kwargs)
        else:
            return super().dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        data = json.loads(request.body)
        username = data.get('username')
        password = data.get('password')
        is_valid_ldap = authenticate(request, username=username, password=password)
        # print(is_valid_ldap)
        if is_valid_ldap:
            # 连接到 LDAP 服务器
            server = Server('ldap://10.1.0.19:389')
            conn = Connection(server, user='sdwebui@cyou-inc.com', password='p@se08h@A%Rl')
            if UserInfo.objects.filter(username=username).exists() == False:
                UserInfo.objects.update_or_create(username=username,permission='用户',login=1,cardid=username,secret_key="",email=username+'@cyou-inc.com')
            userinfo = UserInfo.objects.get(username=username)
            # 绑定连接并搜索用户信息
            if userinfo.phonenumber == "":
                if conn.bind():
                    # 按邮件地址搜索用户
                    base_dn = 'OU=Users,OU=Managed,DC=cyou-inc,DC=com'
                    email = username+'@cyou-inc.com'  # Replace with the desired email address
                    search_filter = f'(&(objectClass=user)(mail={email}))'
                    # 选择需要获取的属性，这里包括mail、extensionAttribute1和cn（用户名）
                    attributes = ['mail', 'extensionAttribute1', 'cn']
                    conn.search(base_dn, search_filter, attributes=attributes, search_scope=SUBTREE)
                    if len(conn.entries) == 1:
                        # 找到了用户，获取邮箱地址、手机号码和用户名
                        user_entry = conn.entries[0]
                        # email_address = user_entry.mail.value if 'mail' in user_entry else 'Email not found'
                        phone_number = user_entry.extensionAttribute1.value if 'extensionAttribute1' in user_entry else 'Phone number not found'
                        # username = user_entry.cn.value if 'cn' in user_entry else 'Username not found'
                        # print(f'Username: {username}')
                        # print(f'Email Address: {email_address}')
                        print(f'Phone Number: {phone_number}')
                        UserInfo.objects.filter(username=username).update(phonenumber=phone_number)
            phone1 = self.get_phonenumber(username)
            # 生成随机的 6 位数字验证码，存储在本地的redis数据库中，并做了六十秒的缓存
            verification_code = str(random.randint(100000, 999999))
            print(verification_code)
            self.handle = redis.Redis(host='192.168.135.130',
                                      port=6379,
                                      db=0,
                                      # password=password,
                                      # decode_responses=True
                                      )
            self.handle.set(username, verification_code, ex=60)
            self.handle.close()
            response = self.main(phone=phone1, code={'code': verification_code})
            if response.status_code == 200:
                return JsonResponse({'message': '发送成功.60S内输入有效！'}, status=200)
            else:
                return JsonResponse({'message': '发送失败.'}, status=201)
        else:
            return JsonResponse({'message': '发送失败，用户名和密码验证未通过！'}, status=201)

    @staticmethod
    def get_phonenumber(username, *args, **kwargs):
        try:
            user_info = UserInfo.objects.get(username=username)
            phonenumber = user_info.phonenumber
        except UserInfo.DoesNotExist:
            phonenumber = None
        return phonenumber

    @staticmethod
    def create_client(access_key_id, access_key_secret):
        config = open_api_models.Config(access_key_id=access_key_id, access_key_secret=access_key_secret)
        config.endpoint = f'dysmsapi.aliyuncs.com'
        return Dysmsapi20170525Client(config)

    @staticmethod
    def main(phone, code, *args, **kwargs):
        client = SendVerificationCodeView_AddAndBindGoogleAuthView.create_client("LTAI5tHmkD5DwJ1HPivyaksg", "5mJ6STlyJZdU7fPpIUUQLtt8fREAH1")
        send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
            phone_numbers=phone,
            sign_name='阿里云短信测试',
            template_code='SMS_154950909',
            template_param=str(code),
        )
        runtime = util_models.RuntimeOptions()
        try:
            return client.send_sms_with_options(send_sms_request, runtime)
        except Exception as error:
            # 如有需要，请打印 error
            return UtilClient.assert_as_string(error.message)

    def get(self, request, *args, **kwargs):
        data = json.loads(request.body)
        username = data.get('username')
        # password = data.get('password')
        # # 获取前端发送的用户名、密码和Google动态口令以及手机验证码
        # google_auth_code = data.get('otp_code')
        # verificationCode = data.get('verificationCode')
        # verification_code = "1"
        # if verificationCode != "0":
        #     self.handle = redis.Redis(host='192.168.135.130',
        #                               port=6379,
        #                               db=0,
        #                               # password=password,
        #                               # decode_responses=True
        #                               )
        #     verification_code = self.handle.get(username).decode()
        #     self.handle.close()
        #     if verificationCode == None:
        #         return JsonResponse({'message': '验证码过期！'}, status=201)
        # # 执行Google动态口令和LDAP以及手机验证码的三因素验证逻辑
        # secret_key = self.get_secret_key(username)
        # # print(secret_key,username)
        # # print(secret_key)
        # if secret_key == "" and verificationCode == "0":
        #     return JsonResponse({'message': '你还没有绑定谷歌秘钥！'}, status=201)
        # is_valid_google_auth = self.validate_google_auth(secret_key, google_auth_code)
        # is_valid_ldap = authenticate(request, username=username, password=password)
        # if (is_valid_google_auth and is_valid_ldap) or (is_valid_ldap and verification_code == verificationCode):
        user_info = UserInfo.objects.get(username=username)
        menus = rolesoperate.getmenus1(self, permission=user_info.permission)
        menus = rolesoperate.remove_empty_children(self,menus)
        menus = rolesoperate.get_ids_without_children(self,menus)
        data={
            'token': username,
            "login" : user_info.login,
            "permission" : user_info.permission,
            "cardid": user_info.cardid,
            "menus":menus
        }
        return JsonResponse(data,status=200)
        # elif is_valid_ldap == True:
        #     return JsonResponse({'message': '验证码输入错误！'}, status=201)
        # else:
        #     return JsonResponse({'message': '用户名和密码验证未通过！'}, status=201)

    @staticmethod
    def get_secret_key(username, *args, **kwargs):
        try:
            user_info = UserInfo.objects.get(username=username)
            secret_key = user_info.secret_key
        except UserInfo.DoesNotExist:
            secret_key = None
        return secret_key

    @staticmethod
    def validate_google_auth(secret_key, google_auth_code):
        totp = pyotp.TOTP(secret_key)
        if totp.verify(google_auth_code):
            return True
        else:
            return False

class generate_google_authenticator(View):
        session = requests.Session  # 创建会话对象.
        @method_decorator(csrf_exempt)
        def dispatch(self, request, *args, **kwargs):
            action = kwargs.pop('action', None)
            if action == 'Google_Registration_Checkup':
                return self.Google_Registration_Checkup(request, *args, **kwargs)
            else:
                return super().dispatch(request, *args, **kwargs)
        @csrf_exempt
        def generate_google_authenticator_qrcode(self,secret_key,username):
            secret_key = secret_key
            data = pyotp.totp.TOTP(secret_key).provisioning_uri(name=username, issuer_name='CY')
            qr = QRCode(
                version=1,
                error_correction=constants.ERROR_CORRECT_L,
                box_size=6,
                border=4,
            )
            try:
                qr.add_data(data)
                qr.make(fit=True)
                img = qr.make_image(fill_color="black", back_color="white")
                buffer = BytesIO()
                img.save(buffer, 'PNG')
                binary_data = buffer.getvalue()
                return binary_data
            except Exception as e:
                print(e)
                return None
        # 返回谷歌二维码
        @csrf_exempt
        def Google_Registration_Checkup(self,request):
            data = json.loads(request.body)
            username = data.get('username')
            secret_key = pyotp.random_base32(64)
            if UserInfo.objects.filter(username=username).exists():
                UserInfo.objects.filter(username=username).update(secret_key=secret_key)
                binary_data = self.generate_google_authenticator_qrcode(secret_key,username)
                return HttpResponse(binary_data, content_type='image/png')
            else:
                UserInfo.objects.filter(username=username).update_or_create(username=username,secret_key=secret_key,phonenumber="",permission='用户',login=1,cardid=username,email=username+'@cyou-inc.com')
                binary_data = self.generate_google_authenticator_qrcode(secret_key, username)
                return HttpResponse(binary_data, content_type='image/png')
        # 用户不存在于数据库中